Release 10.1A: OpenEdge Development:
Progress 4GL Reference
RUN statement
Calls a Progress procedure. This procedure can be local to or remote from the current session, external from or internal to the current procedure, and either synchronous or asynchronous. When a local or remote procedure is called synchronously, the calling procedure resumes execution only after the called procedure completes execution. When a remote procedure is called asynchronously, the calling procedure resumes execution immediately after the remote request is sent to the AppServer.
The RUN statement can also call functions or routines that reside in the Windows Dynamic Link Libraries (DLLs) or in UNIX shared libraries. The called routine must first be declared like a Progress internal procedure. The procedure declaration must be in the same file as the RUN statement.
You can also use the RUN statement to create and associate a procedure object with a Web service, and invoke a Web service operation.
Syntax
Use the following syntax to create and associate a procedure object with a Web service:
Use the following syntax to invoke a Web service operation:
extern-proc-nameThe name of the (local or remote) external procedure to run. On UNIX, external procedure names are case sensitive; in Windows, they are not. If you specify a relative pathname, Progress searches the directories (and libraries, on platforms that support libraries) defined in the
PROPATHenvironment variable. Withextern-proc-name, you can specify a local or remote procedure.VALUE (extern-expression)An expression that returns the name of the (local or remote) external procedure you want to run.
path-name<<member-name>>The pathname of an r-code library and the name of an r-code file in that library. To specify an r-code file in a library, you must use the double angle brackets as shown. If you specify a relative library pathname, Progress searches the libraries defined in the
PROPATHenvironment variable.PERSISTENT [SETproc-handle]Specifies that the external procedure be run and created (instantiated) as a persistent procedure. You can return the handle to the persistent procedure in
proc-handle, a field, variable, or output parameter defined with the HANDLE data type. If you do not specifyproc-handle, you can find the procedure handle for this procedure using the FIRST-PROCEDURE and LAST-PROCEDURE attributes of the SESSION system handle. You can use PERSIST as an abbreviation for PERSISTENT.A persistent procedure creates and maintains its context after it returns to the caller. Other external procedures can access this context through procedure triggers and internal procedures defined in the persistent procedure. Thus, a RUN statement that runs and creates a persistent procedure context is referred to as an
instantiating RUN statement.The order of the PERSISTENT option and the ON SERVER option is interchangeable.
ON [SERVER]server-handleTells Progress to run the procedure remotely in the AppServer that the HANDLE variable,
server-handle, refers to.With the ASYNCHRONOUS option,
server-handlecauses the called procedure to run asynchronously in the remote session. Control returns immediately to the statement following the RUN statement. Execution of any specifiedevent-internal-procedure. occurs in the context of an I/O blocking or PROCESS EVENTS statement.The order of the PERSISTENT option and the ON SERVER option is interchangeable.
ON [SERVER]session-handleTells Progress to run the procedure locally in the current OpenEdge session, specified by the value of the SESSION system handle (
session-handle).With the ASYNCHRONOUS option,
Note: This order of execution is different than for a remote procedure call using thesession-handlecauses the called procedure to run synchronously in the local session, followed immediately by execution of any specifiedevent-internal-procedure. Only after execution of the specifiedevent-internal-proceduredoes control return to the statement following the RUN statement.server-handle.The order of the PERSISTENT option and the ON SERVER option is interchangeable.
TRANSACTION DISTINCTTells Progress not to propagate the calling procedure’s transaction to the AppServer. Although the current version of Progress does not allow transaction propagation, future versions might. Thus, to accommodate this possibility without breaking current code, the current version of Progress allows you to specify this option with
Note: It is an error to specify TRANSACTION DISTINCT with aserver-handle.session-handle.ASYNCHRONOUS [ SETasync-request-handle]Specifies that the remote procedure is to be called as an asynchronous request. By default, the remote procedure is called synchronously. The handle to the asynchronous request is returned in
async-request-handle, which must be a field, variable, or parameter defined with the HANDLE data type. If you specify ASYNCHRONOUS but do not specify SETasync-request-handle, you can find the handle for the asynchronous request using the LAST-ASYNC-REQUEST attribute of theserver-handlespecified by the ON option. You can also locate the asynchronous request handle by walking the chain between the FIRST-ASYNC-REQUEST and LAST-ASYNC-REQUEST attributes ofserver-handle, searching on the PROCEDURE-NAME attribute of each request handle.For a Web service operation invoked asynchronously, the handle that is set to the asynchronous request object created for the asynchronous request.
EVENT-PROCEDUREevent-internal-procedureSpecifies a quoted string or character expression representing the name of an internal procedure that resides within
procedure-context. When the response from the asynchronous request is received (that is, a PROCEDURE-COMPLETE event occurs), the specified internal procedure is called during subsequent execution of a PROCESS EVENTS or I/O-blocking statement (such as WAIT-FOR). The specifiedevent-internal-procedureprocesses any parameters and errors returned from the asynchronous request. If not specified, no event procedure is executed when the PROCEDURE-COMPLETE event occurs for the asynchronous request.For information on how the
event-internal-procedurehandles parameters from the asynchronous request, see theparameteroption. For information on how theevent-internal-procedurehandles errors from the asynchronous request, see the NO-ERROR option.INprocedure-contextA handle to an active procedure that contains the internal procedure specified by
event-internal-procedure. If not specified, THIS-PROCEDURE is used as theprocedure-contextvalue.(parameter[,parameter]...)Specifies one or more parameters to pass to the called procedure.
For the parameter passing syntax, see the Parameter passing syntax reference entry in this book.
Parameters must be defined in the called procedure. (See the DEFINE PARAMETER statement reference entry.) They must be passed in the same order as they are defined, and they must have compatible data types. Progress attempts to convert values for data types that do not match. If Progress cannot convert the value for a mismatched data type, the RUN statement fails with an error condition.
For OUTPUT parameters of an asynchronous remote procedure call only, you can specify
parameter-nameASdata-typeas a prototype. Theparameter-nameis an arbitrary place-holder name anddata-typemust specify the Progress data type of the corresponding OUTPUT parameter in the asynchronous remote procedure. You can also specify OUTPUT parameters for an asynchronous remote procedure using a localfield,variable, or TABLEtemp-table-name. However, note that the asynchronous remote procedure does not return any values to OUTPUT or INPUT-OUTPUT parameters on the RUN statement. These parameters are place holders only for values returned by the remote procedure to the specifiedevent-internal-procedure.Any specified
event-internal-procedurecan define only INPUT parameters and must define one INPUT parameter for each OUTPUT or INPUT-OUTPUT parameter defined in the asynchronous remote procedure. Eachevent-internal-procedureINPUT parameter must match the corresponding remote procedure OUTPUT or INPUT-OUTPUT parameter in order and data type. (As with other procedures, Progress attempts to convert the values for data types that do not match.) The asynchronous remote procedure returns the values of these parameters to the INPUT parameters of theevent-internal-procedureafter the remote procedure completes execution and the client session processes the associated PROCEDURE-COMPLETE event.If you are running an internal procedure declared as a Windows dynamic link library (DLL) or UNIX shared library routine, you must match any RETURN parameter specified by a DEFINE PARAMETER statement with a corresponding OUTPUT parameter in the RUN statement. If the internal procedure does not specify the RETURN parameter, do not specify the corresponding OUTPUT parameter in the RUN statement.
For external procedures, the parenthesized list of run-time parameters must precede any compile-time arguments.
argumentA constant, field name, variable name, or expression that you want to pass as a compile-time argument to the external procedure you are running.
When you pass arguments to an external procedure, Progress converts those arguments to character format. Progress recompiles the called procedure, substitutes arguments, and then runs the procedure. You cannot precompile a procedure to which you pass arguments. (If you use shared variables instead of arguments, the procedure can be precompiled. This yields more efficient code.)
Note: You cannot pass compile-time arguments in a call to an internal procedure.NO-ERRORSpecifies that any ERROR conditions that occur in the attempt to run the procedure are suppressed. This does not mean that all errors produced by the called procedure are suppressed; only errors caused by the RUN statement itself. Also, if a specified local or synchronous remote procedure performs a RETURN ERROR, an ERROR is raised for the RUN statement. After the RUN statement completes, you can check the ERROR-STATUS system handle for information on any errors that occurred.
For an asynchronous remote procedure, the result depends on where the errors occur. If the errors occur during the send phase of the asynchronous request, this raises the ERROR condition on the RUN statement in the client (which you can suppress with NO-ERROR). If the errors occur during execution of the remote request and are returned by the AppServer, this results in an implied NO-ERROR on the RUN statement, and you must check the ERROR-STATUS system handle as well as the attributes of the asynchronous request handle (
async-request-handle) for any error returns in the specifiedevent-internal-procedure. If the asynchronous remote procedure returns an unhandled STOP condition, ERROR-STATUS:ERROR andasync-request-handle:ERROR are both set to FALSE andasync-request-handle:STOP is set to TRUE.The RUN statement returns ERROR or STOP for a variety of events depending on the type of procedure that is executed, which includes any of the following:
- All types of procedures
- Local procedures
- All remote procedures
- Synchronous remote procedures
- Asynchronous remote procedures
Table 45 summarizes when Progress raises ERROR or STOP for each type of procedure.
Table 45: RUN statement ERROR and STOP conditions Procedure type Condition Event All procedures ERROR The run-time parameters are not compatible. ERROR Any specified INproc-handleoption is invalid. ERROR A called internal procedure is not found in the specified external procedure. ERROR The procedure returns ERROR. STOP The procedure returns an unhandled STOP. Local procedures STOP The specified procedure is not found.1 STOP An attempted compile of the procedure failed.1 All remote procedures ERROR The specified procedure is not found. ERROR An attempted compile of the procedure failed. ERROR The specified ON SERVERserver-handleoption is invalid. ERROR Theserver-handleis not currently connected to some AppServer. ERROR One of the parameters specified byparameterhas a data type of BUFFER or MEMPTR. ERROR The PROXY attribute ofproc-handle(from the INproc-handleoption) is TRUE and the associated server handle is no longer connected to an AppServer. Synchronous remote procedures ERROR The ASYNC-REQUEST-COUNT attribute on theserver-handleis greater than zero (0). Asynchronous remote procedures ERROR The REMOTE attribute ofprocedure-contextis set to TRUE.In addition, under the following conditions, a STOP condition occurs in the context of the I/O-blocking or PROCESS EVENTS statement that invokes any specified
event-internal-procedure:- Progress cannot locate the specified
event-internal-procedure, for example, because the spelling ofevent-internal-procedureis not identical to the name of the internal procedure definition intended for use as the event procedure.- The procedure handle that specifies the
procedure-contextto contain the definition ofevent-internal-procedureis not a valid procedure handle.intern-proc-nameThe name of the (local or remote) internal procedure you want to run. The procedure must be declared in the same procedure file as the RUN statement that calls it unless you specify the IN
proc-handleoption or use a super procedure. If you do not specify the INproc-handleoption and there is no internal procedure declared by the specified name, Progress tries to run an external procedure with the specified name. If the internal procedure is remote, you must specify the INproc-handleoption to identify the remote persistent procedure that defines the internal procedure on an AppServer.VALUE (intern-expression)An expression that evaluates to the name of the internal procedure you want to run.
INproc-handleSpecifies the handle of the external procedure that declares the internal procedure you want to run. You can specify
proc-handleas a field, variable, parameter, or expression that specifies a valid procedure handle or proxy (remote) persistent procedure handle.portTypeNameThe name of a Web service PortType as specified in the WSDL file.
hPortTypeA handle to a procedure object that encapsulates a Web service operation.
hWebServiceA handle to the server object bound to the Web service.
operationNameThe name of a Web service operation specified in a WSDL file.
ExamplesThe following procedure displays a simple menu. The user’s selection is stored in the selection variable. The INDEX function returns an integer value that indicates the position of the user’s selection in a string of characters ("12345"). If the value in the selection variable is not in the list of values, the INDEX function returns a 0. The VALIDATE statement ensures that the INDEX function did not return a zero. If it did, VALIDATE displays the message “Not a valid choice.”
In the RUN statement, the INDEX function returns the position of the user’s selection in a character string. Suppose you chose option 2 from the menu. That option occupies the second position in the "12345" character string. Therefore, the INDEX function returns the number two (2). Using this number, the RUN statement reads, RUN VALUE(programs[2]). According to the assignments at the top of the procedure, the value of programs[2] is custedit.p. Now the RUN statement reads, RUN custedit.p, and the
r-run.pprocedure runs thecustedit.pprocedure.The following two external procedures,
r-runper.pandr-perprc.p, illustrate the PERSISTENT and INproc-handleoptions of the RUN statement. The first procedure, a non-persistent control procedure, sets up a window to run and manage the second procedure as a persistent procedure.
The control procedure,
r-runper.p, runsr-perprc.peach time you choose the Start Customer Query button. Each time it runs,r-perprc.pcreates (instantiates) an additional context instance for the persistent procedure, including an additional window to open customer queries. When you choose the Recall All Hidden Queries button from the control window,r-runper.pcalls the recall-query internal procedure in each instance ofr-perprc.pto redisplay its window. Similarly, when you choose the Exit button,r-runper.pcalls the destroy-query internal procedure in each instance ofr-perprc.pto delete its context instance;r-runper.pthen applies the RETURN event to itself to terminate by completing the WAIT-FOR statement.The
r-perprc.pprocedure sets up a customer query that you can re-open three different ways: by name, by balance, or by credit. Each instance ofr-perprc.pmaintains a separate query for its own local customer buffer. Note that by testing and setting attributes of the THIS-PROCEDURE system handle,r-perprc.pcan run either persistently or non-persistently. The basic difference is how the procedure maintains its own context. For example, when running persistently, it defines a trigger on the bCancel button to run its own deletion procedure, destroy-query, to terminate; when running non-persistently, it completes a WAIT-FOR statement with the bCancel button to terminate.The following example shows how you might implement an asynchronous request. The procedure
r-async.pruns persistently from a user-interface trigger, perhaps in response to a menu choice. This procedure, in turn, sends a request to runrunReport.pon an AppServer, which provides an inventory report for the specified date.When
r-async.preturns, the user-interface trigger ends and the application returns to its WAIT-FOR state. The user continues to use the application in the normal way while the inventory report runs on the AppServer.When
runReport.pfinishes running, a PROCEDURE-COMPLETE event occurs. This event causes the internal procedure reportDone to run automatically within the context of the application’s WAIT-FOR statement. Whatever the user is doing in the application, reportDone displays an alert box indicating whether or not the inventory report completed successfully and the number of lines (numLines) that were output for the report. (The bolded 4GL indicates the code required to support asynchronous requests to runrunReport.p.)
Notes
- 4GL procedures can be run recursively (a procedure can run itself).
- In Version 6, Progress uses time stamps by default to verify that r-code is consistent with the database schema. Some releases of Version 6 provide optional support for CRC codes instead of time stamps. Progress Version 7 and later uses CRC codes by default. If you want to use time stamps instead, specify the Time Stamp (-tstamp) parameter when you connect to a database.
- When a RUN statement raises the STOP condition, Progress displays the resulting messages on the current output device, even if you specify NO-ERROR. Progress also writes these messages to the ERROR-STATUS system handle, but sets ERROR-STATUS:ERROR to FALSE.
- You can run an internal procedure that is declared in the current external procedure or in the procedure you specify with the IN
proc-handleoption. The procedure handle specified by the INproc-handleoption can specify either a valid persistent procedure instance or an external procedure that is active on the procedure call stack. The handle can also specify the current external procedure using the THIS-PROCEDURE system handle. You can check the validity of any procedure handle using the VALID-HANDLE function.- A called external procedure uses any arguments passed to it from the calling procedure by referring to those arguments as numbers enclosed in braces { }. The first argument is {1}, the next is {2}, etc. Any arguments the called procedure does not use are ignored, and any missing arguments are treated as null values. (Note that the null is a legal value in a WHERE or WITH clause, but its occurrence can cause an error at other points in a called procedure.)
- To run an r-code file stored in a library that is not on
PROPATH, you must specify the name of the library and the name of the r-code file in the library. Specify these names in the formpath-name<<member-name>>, wherepath-nameis the pathname of the library andmember-nameis the name of the r-code file. For example, if you have an r-code file calledappmenu.rin a library whose pathname is/usr/foo/app.pl, you use this command to run it:
- When you run a procedure and do not specify the PERSISTENT option, Progress first looks for an internal procedure with the name you specify (this search is not case sensitive). If you specify a procedure in the form
path-name<<member-name>>, Progress looks for an internal procedure with a name in that form. If you specify the PERSISTENT option, or if no internal procedure is found, Progress searches all the directories and libraries inPROPATHfor a usable r-code file of the same name. Progress also checks to see if the procedure was modified since the last time it was run. If there is a usable r-code file, there is no point in performing the compilation. The RUN statement always uses an existing r-code file before using a session compile version of a procedure.If you do not want Progress to check whether the procedure has been modified before using the r-code, use the Quick Request (-q) parameter.
- When running an external procedure, it is good practice to specify the name of the source file in the RUN statement. For example, to run
r-exit.pyou specify the following:
When you specify a suffix or file extension (such as .p), Progress first tries replacing that suffix or extension with .r and searches the first directory on your
PROPATHfor a file with that name. If the r-code file is not found, then it reverts to the original suffix and searches for a source file with that name. If the source file is not found in the firstPROPATHdirectory, then Progress searches for an r-code file and then a source file in each subsequent directory on yourPROPATHuntil a file is found.If you specify the .r suffix in the RUN statement, then Progress searches only for an r-code file in each directory on your
PROPATH. If you omit the extension, then Progress first adds a .r to the name you specify and searches the first directory for an r-code file with that name. If none is found, then Progress searches for a source file with no suffix or extension.- You cannot run an internal procedure with the PERSISTENT option.
- An external procedure called with the PERSISTENT option runs in the same way as a non-persistent procedure with these differences:
- The procedure does not go out of scope when it returns: its context and most of its allocated resources remain active, including input parameters, widgets, variables, buffers, temporary tables, work tables, and triggers created during procedure execution. However, all static dialog boxes, their child widgets, and related triggers created during its execution are destroyed when the procedure returns to the caller. This makes all other windows and dialog boxes in the application available for input.
- All buffers passed as parameters to a persistent procedure are treated as local buffers in the persistent context. When the procedure instantiation returns, the output value of the buffer parameter is returned, as usual, to the calling procedure. However, any cursor positioning established during execution of the instantiating RUN statement is lost to the persistent context once the procedure returns; Progress creates a copy of the buffer parameter and resets its cursors as an initially defined local buffer.
- If the procedure obtains any schema share locks (through database access) while executing, these remain in effect after the procedure returns, until the procedure is deleted.
Note: If you run an application that creates persistent procedures from an ADE tool (for example, the Procedure Editor or User Interface Builder), that tool removes all instances of persistent procedures still created when the application terminates.- Each time you run a procedure persistently, you create a new instance of its procedure context. All of its data, buffers, and widgets are duplicated and separately managed by the new instantiation until the procedure instance is deleted.
- Transaction scoping is the same whether you run a procedure as persistent or not. Any transaction which begins inside a persistent procedure is scoped to the block that starts the transaction.
- If you run a procedure with the PERSISTENT option and a STOP or QUIT condition or a RETURN ERROR occurs during execution of the procedure, the procedure returns as a non-persistent procedure.
- All shared variables, buffers, temporary tables, ProDataSet objects, work tables, and queries remain in scope as long as a persistent procedure instance remains that accesses them. This is true even if the procedure (persistent or non-persistent) that originally defined the shared data has gone out of scope. Shared data can go out of scope only when no persistent procedure remains that references it.
- You cannot run a procedure with the PERSISTENT option in which you have defined shared streams or shared frame, browse, or menu widgets. Doing so causes Progress to raise ERROR on the RUN statement.
- You can remove an instance of a persistent procedure using the DELETE PROCEDURE statement. When you delete the procedure instance, its context goes out of scope and all allocated resources are returned to the system. If the procedure has shared dependencies on the call stack, the delete pends until the dependencies are cleared.
- To run a Windows DLL routine as an internal procedure, you must reference the DLL in a PROCEDURE statement and define its parameters in the associated internal procedure block. For more information on accessing DLL routines from Progress, see OpenEdge Development: Programming Interfaces manual.
- To run a UNIX shared library routine as an internal procedure, you must reference the UNIX shared library in a PROCEDURE statement and define its parameters in the associated internal procedure block. You can declare an internal procedure as a routine in a UNIX shared library in the same manner as declaring a DLL routine. The one exception is that the ORDINAL option is not applicable to UNIX and will be ignored.
- You can define triggers on procedure handles (procedure triggers). You can apply events to any procedure trigger defined either within a persistent procedure or within any external procedure that is active on the procedure call stack.
This code fragment assumes that a trigger is defined within
persproc.pfor the RETURN event on the THIS-PROCEDURE handle. For more information on defining and executing procedure triggers, see OpenEdge Development: Progress 4GL Handbook .- If you are using Progress with a DataServer that supports stored procedures, the RUN statement has extensions that allow you to execute a stored procedure. For more information, see the entry for the RUN STORED-PROCEDURE statement and the appropriate OpenEdge DataServer Guides, OpenEdge Data Management: DataServer for Microsoft SQL Server , OpenEdge Data Management: DataServer for ODBC , and OpenEdge Data Management: DataServer for ORACLE .
- If you RUN a procedure multiple times within a session, changing the procedure between runs, you must manually recompile the procedure each time. Otherwise, the procedure’s last r-code, which persists for a session, is what is run and the changes do not appear.
- An asynchronous call to a remote procedure (using the ASYNCHRONOUS option) causes the RUN statement to return control immediately to the following statement in the local context, whether or not the remote procedure has completed execution.
- If an asynchronous call to a remote procedure does not raise a STOP or ERROR condition, Progress:
- Increments the
server-handle:ASYNC-REQUEST-COUNT attribute.- Increments the
proc-handle:ASYNC-REQUEST-COUNT attribute, if PERSISTENT is specified for a remote external procedure or INproc-handleis specified for a remote internal procedure.- Sets the
async-request-handle:COMPLETE attribute to FALSE, indicating that the request has not completed execution.- Sets the
async-request-handle:EVENT-PROCEDURE attribute to the value ofevent-internal-procedure, ifevent-internal-procedureis specified.- Sets the
async-request-handle:EVENT-PROCEDURE-CONTEXT attribute to the value ofprocedure-context, ifprocedure-contextis specified.- Submits the request for execution by the AppServer.
- Progress checks the syntax of the ON SERVER option at run time. This allows you to use a single HANDLE variable that you can set either to a server handle value or the value of the current SESSION handle. Thus, you can use the same RUN statement to execute a procedure remotely in an AppServer or locally depending on application conditions.
- When you specify the ON SERVER option with the SESSION system handle, the RUN statement is functionally similar to not specifying the ON SERVER option at all. That is, the two RUN statements in the following code perform the same function:
Allowing the same ON SERVER option to specify either a local session or a remote AppServer session facilitates code generation for applications like the Progress AppBuilder.
With the ASYNCHRONOUS option, using the ON SERVER SESSION option causes the called procedure to run synchronously in the local session, followed immediately by execution of any specified
event-internal-procedure. Only after execution of the specifiedevent-internal-proceduredoes control return to the statement following the RUN statement. This synchronous local execution includes the following differences in error handling from asynchronous execution on an AppServer using ON SERVERserver-handle:
- If an unhandled ERROR condition occurs during execution of the called local procedure, the error message is displayed on the local output device. This is different from remote execution, where any error message is written to the AppServer log file.
- If the called local procedure causes an ERROR or STOP condition to be raised in the calling procedure (a file not found, mismatched parameters, a compile error, and explicit execution of a RETURN ERROR or STOP statement), Progress sends the associated message to the standard output device and sets ERROR-STATUS:ERROR appropriately. This is different from remote execution, where Progress in most cases attaches the associated message to the ERROR-STATUS system handle.
- Also, if the called local procedure causes an ERROR or STOP condition to be raised in the calling procedure (as in the previous note), Progress raises the condition on the RUN statement, as for a local RUN statement without the ON SERVER option. This is different from remote execution, where Progress does not raise the condition on the calling RUN statement. You can work around this for the ON SERVER SESSION case by coding each asynchronous RUN statement with the NO-ERROR option and possibly surrounding it with a DO ON STOP UNDO, LEAVE block.
- For more information on AppServers and calling remote procedures synchronously or asynchronously, see OpenEdge Application Server: Developing AppServer Applications .
- For more information on asynchronous invocation of Web service operations, see OpenEdge Development: Web Services .
See also
{ } Argument reference, { } Include file reference, APPLY statement, Asynchronous request object handle, CODEBASE-LOCATOR system handle, COMPILE statement, CREATE SAX-READER statement, DEFINE PARAMETER statement, DELETE PROCEDURE statement, ON statement, Parameter passing syntax, PROCEDURE statement, RUN STORED-PROCEDURE statement, THIS-PROCEDURE system handle, VALID-HANDLE function, Widget phrase
|
Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095 |